#include "IWall.h"
#include <math.h>
#include <time.h>

// Hbegin
void IWall::Hbegin(int rx, int tx) {
#if defined NRF5
    // 串口设置
    rx = g_PinID[rx];
    tx = g_PinID[tx];
    MicroBitPin *rxpin = getMicroBitPin(rx);
    MicroBitPin *txpin = getMicroBitPin(tx);
    uBit.serial.redirect(txpin->name, rxpin->name);
    uBit.serial.setRxBufferSize(64);
    // 解决发送BUG
    delay(100);
#endif
}

// 读取串口数据
void IWall::serial_read() {
    while (!(Serial.available())) {yield();}
    Serial.readBytesUntil('\n', receive_buffer, 64);
}

// 查找计时器
int IWall::lookup_timer(String timer) {
    for (int i = 0; i < tim_number; i ++) {
        if (timer.equals(tim[i].name)) {
            return i;
        }
    }
    return -1;
}

// 查找角色
int IWall::lookup_sprite(String character) {
    for (int i = 0; i < spr_number; i ++) {
        if (character.equals(spr[i].name)) {
            return i;
        }
    }
    return -1;
}

// 查找文本框
int IWall::lookup_textarea(String textarea) {
    for (int i = 0; i < txt_number; i ++) {
        if (textarea.equals(txt[i].name)) {
            return i;
        }
    }
    return -1;
}

// iWall初始化
void IWall::iWall_Init() {
    Hbegin(1, 0);
    Serial.begin(115200);
    // 发送字符串
    Serial.write("D_Init\r\n");
    serial_read();
}

// 新计时器
String IWall::iWall_createTimer() {
    // 计时器名称
    tim[tim_number].name = "iWall_timer_";
    tim[tim_number].name.concat(tim_count);
    // 获取当前时间到计时器中
    tim[tim_number].millisecond = millis();
    tim_number += 1;
    tim_count += 1;
    // 返回标识符
    return tim[tim_number - 1].name;
}

// 获取计时器[TIMER]的时间（毫秒）
int IWall::iWall_GetTimerValue(String timer) {
    // 找到角色
    int idx = lookup_timer(timer);
    if (idx == -1) return -1;
    return millis() - tim[idx].millisecond;
}

// 清零计时器[TIMER]
void IWall::iWall_ClearTimer(String timer) {
    // 找到角色
    int idx = lookup_timer(timer);
    if (idx == -1) return;
    tim[idx].millisecond = millis();
}

// 创建角色 类型[CHARACTER_TYPE] X[POSITION_X] Y[POSITION_Y]
String IWall::iWall_createCharacter(String character_type, int position_x, int position_y) {
    // 生成角色相关信息放入到结构体中
    // 角色名称
    spr[spr_number].name = "iWall_sprite_";
    spr[spr_number].name.concat(spr_count);
    // 角色中心点坐标
    spr[spr_number].center_x = position_x;
    spr[spr_number].center_y = position_y;
    // 角色是否隐藏
    spr[spr_number].visibility = true;
    // 角色类型、宽和高
    int start = 0;
    for (int i = 0; i < character_type.length(); i ++) {
        if (character_type[i] == '_' && start == 0) {
            // substring包左不包右
            // 角色类型
            spr[spr_number].type = character_type.substring(0, i).toInt();
            start = i + 1;
        } else if (character_type[i] == '_' && start != 0) {
            // 角色宽
            spr[spr_number].width = character_type.substring(start, i).toInt();
            start = i + 1;
        } else if (i == character_type.length() - 1) {
            // 角色高
            spr[spr_number].height = character_type.substring(start).toInt();
        }
    }
    // 角色图形方向
    spr[spr_number].graph_direct = 0;
    // 角色运动方向
    spr[spr_number].motion_direct = 0;
    // 角色遇到边缘处理方式
    spr[spr_number].edge_mode = 0;
    // 角色数组包含角色的当前数量
    spr_number += 1;
    // 角色数组创建角色的总数量
    spr_count += 1;
    // 拼接字符串
    send_string = "C_New:";
    send_string.concat(spr[spr_number - 1].type);
    send_string.concat(",");
    send_string.concat(spr[spr_number - 1].center_x);
    send_string.concat(",");
    send_string.concat(spr[spr_number - 1].center_y);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
    return spr[spr_number - 1].name;
}

// 删除角色[CHARACTER]
void IWall::iWall_deleteCharacter(String character) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 从角色数组中删除
    for (int j = idx; j < spr_number; j ++) {
        spr[j] = spr[j + 1];
    }
    spr_number -= 1;
    // 拼接字符串
    send_string = "C_Del:";
    send_string.concat(idx);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER]移动[STEP]
void IWall::iWall_characterMove(String character, int step) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 根据移动方向更新角色中心点坐标
    // 先确定所需要移动后的位置
    int distance_x = spr[idx].center_x;
    int distance_y = spr[idx].center_y;
    switch (spr[idx].motion_direct) {
        // 上
        case 0: distance_y -= step; break;
        // 下
        case 1: distance_y += step; break;
        // 左
        case 2: distance_x -= step; break;
        // 右
        case 3: distance_x += step; break;
        // 左上
        case 4: distance_x -= step; distance_y -= step; break;
        // 右上
        case 5: distance_x += step; distance_y -= step; break;
        // 左下
        case 6: distance_x -= step; distance_y += step; break;
        // 右下
        case 7: distance_x += step; distance_y += step; break;
    }
    // 根据角色碰到边缘处理方式更新中心点坐标
    int dx, dy; // 角色到边缘的距离
    int direct_x, direct_y; // 方向矢量
    switch (spr[idx].edge_mode) {
        // 飞出
        case 0:
            break;
        // 停止
        case 1:
            // 判断角色到边缘的距离
            dx = 0;
            dy = 0;
            if (distance_x < 0) dx -= distance_x;
            if (distance_x > 33) dx = 33 - distance_x;
            if (distance_y < 0) dy -= distance_y;
            if (distance_y > 29) dy = 29 - distance_y;
            if (dx !=0 || dy != 0) {
                if (abs(dx) > abs(dy)) {
                    distance_x += dx;
                    distance_y += distance_y > spr[idx].center_y ? - abs(dx) : abs(dx);
                } else {
                    distance_x += distance_x > spr[idx].center_x ? - abs(dy) : abs(dy);
                    distance_y += dy;
                }
            }
            break;
        // 反弹
        case 2:
            // 分解方向矢量
            switch (spr[idx].motion_direct) {
                case 0: direct_x = 0; direct_y = -1; break;
                case 1: direct_x = 0; direct_y = 1; break;
                case 2: direct_x = -1; direct_y = 0; break;
                case 3: direct_x = 1; direct_y = 0; break;
                case 4: direct_x = -1; direct_y = -1; break;
                case 5: direct_x = 1; direct_y = -1; break;
                case 6: direct_x = -1; direct_y = 1; break;
                case 7: direct_x = 1; direct_y = 1; break;
            }
            // 确定反弹后的坐标值
            distance_x = abs(distance_x);
            distance_y = abs(distance_y);
            if (direct_x != 0) direct_x = pow(-1, distance_x / 33);
            if (direct_y != 0) direct_y = pow(-1, distance_y / 29);
            if (direct_x == -1) distance_x = 33 + direct_x * distance_x % 33;
            if (direct_x == 1) distance_x = distance_x % 33;
            if (direct_y == -1) distance_y = 29 + direct_y * distance_y % 29;
            if (direct_y == 1) distance_y = distance_y % 29;
            // 确定反弹后的方向
            if (direct_x == 0 && direct_y == -1) spr[idx].motion_direct = 0;
            if (direct_x == 0 && direct_y == 1) spr[idx].motion_direct = 1;
            if (direct_x == -1 && direct_y == 0) spr[idx].motion_direct = 2;
            if (direct_x == 1 && direct_y == 0) spr[idx].motion_direct = 3;
            if (direct_x == -1 && direct_y == -1) spr[idx].motion_direct = 4;
            if (direct_x == 1 && direct_y == -1) spr[idx].motion_direct = 5;
            if (direct_x == -1 && direct_y == 1) spr[idx].motion_direct = 6;
            if (direct_x == 1 && direct_y == 1) spr[idx].motion_direct = 7;
            break;
    }
    spr[idx].center_x = distance_x;
    spr[idx].center_y = distance_y;
    // 拼接字符串
    send_string = "C_Mov:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(step);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER]设置类型[CHARACTER_TYPE]
void IWall::iWall_characterSetGraph(String character, String character_type) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 根据角色类型信息修改类型、宽和高
    int start = 0, width, height;
    for (int i = 0; i < character_type.length(); i ++) {
        if (character_type[i] == '_' && start == 0) {
            // substring包左不包右
            // 角色类型
            spr[idx].type = character_type.substring(0, i).toInt();
            start = i + 1;
        } else if (character_type[i] == '_' && start != 0) {
            // 角色宽
            width = character_type.substring(start, i).toInt();
            start = i + 1;
        } else if (i == character_type.length() - 1) {
            // 角色高
            height = character_type.substring(start).toInt();
        }
    }
    if (spr[idx].graph_direct == 0 || spr[idx].graph_direct == 1) {
        spr[idx].width = width;
        spr[idx].height = height;
    }
    if (spr[idx].graph_direct == 2 || spr[idx].graph_direct == 3) {
        spr[idx].width = height;
        spr[idx].height = width;
    }
    // 拼接字符串
    send_string = "C_SetGraph:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(spr[idx].type);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER]设置[GRAPHDIRECT]
void IWall::iWall_characterSetGraphDirect(String character, int graphDirect) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 修改角色的宽和高
    if (!(((spr[idx].graph_direct == 0 || spr[idx].graph_direct == 1) && (graphDirect == 0 || graphDirect == 1))
        || ((spr[idx].graph_direct == 2 || spr[idx].graph_direct == 3) && (graphDirect == 2 || graphDirect == 3)))) {
        int tmp = spr[idx].width;
        spr[idx].width = spr[idx].height;
        spr[idx].height = tmp;
    }
    spr[idx].graph_direct = graphDirect;
    // 拼接字符串
    send_string = "C_SetGDir:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(spr[idx].graph_direct);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER]设置[MOTIONDIRECT]
void IWall::iWall_characterSetMotionDirect(String character, int motionDirect) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 修改角色的运动方向
    spr[idx].motion_direct = motionDirect;
    // 拼接字符串
    send_string = "C_SetMDir:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(spr[idx].motion_direct);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER]移动到X[POSITION_X]Y[POSITION_Y]
void IWall::iWall_characterSetXY(String character, int position_x, int position_y) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 修改角色的中心点
    spr[idx].center_x = position_x;
    spr[idx].center_y = position_y;
    // 拼接字符串
    send_string = "C_XY:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(spr[idx].center_x);
    send_string.concat(",");
    send_string.concat(spr[idx].center_y);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER]设置[AXIS]为[AXIS_NUMBER]
void IWall::iWall_characterSetAxis(String character, int axis, int axis_number) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 修改角色中心点
    switch (axis) {
        case 0: spr[idx].center_x = axis_number; break;
        case 1: spr[idx].center_y = axis_number; break;
    }
    // 拼接字符串
    send_string = "C_XY:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(spr[idx].center_x);
    send_string.concat(",");
    send_string.concat(spr[idx].center_y);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER]X偏移[OFFSET_X]Y偏移[OFFSET_Y]
void IWall::iWall_characterSetXYOffset(String character, int offset_x, int offset_y) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 修改角色中心点
    spr[idx].center_x += offset_x;
    spr[idx].center_y += offset_y;
    // 拼接字符串
    send_string = "C_XY:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(spr[idx].center_x);
    send_string.concat(",");
    send_string.concat(spr[idx].center_y);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER][AXIS]偏移[AXIS_NUMBER]
void IWall::iWall_characterSetAxisOffset(String character, int axis, int axis_number) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 修改角色中心点
    switch (axis) {
        case 0: spr[idx].center_x += axis_number; break;
        case 1: spr[idx].center_y += axis_number; break;
    }
    // 拼接字符串
    send_string = "C_XY:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(spr[idx].center_x);
    send_string.concat(",");
    send_string.concat(spr[idx].center_y);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 获得角色[CHARACTER][AXIS]坐标
int IWall::iWall_characterGetXY(String character, int axis) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return -999;
    // 返回角色的中心点坐标值
    switch (axis) {
        case 0: return spr[idx].center_x;
        case 1: return spr[idx].center_y;
    }
}

// 获得角色[CHARACTER]图形方向
int IWall::iWall_characterGetGraphDirect(String character) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return -1;
    // 返回角色的图形方向
    return spr[idx].graph_direct;
}

// 角色[GRAPHDIRECT]
int IWall::iWall_GraphDirect(int graphDirect) {
    // 返回图形方向常量
    return graphDirect;
}

// 获得角色[CHARACTER]运动方向
int IWall::iWall_characterGetMotionDirect(String character) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return -1;
    // 返回角色的运动方向
    return spr[idx].motion_direct;
}

// 角色[MOTIONDIRECT]
int IWall::iWall_MotionDirect(int motionDirect) {
    // 返回运动方向常量
    return motionDirect;
}

// 角色[CHARACTER][VISIBILITY]
void IWall::iWall_characterSetVisible(String character, bool visibility) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 修改角色是否隐藏
    spr[idx].visibility = visibility;
    // 拼接字符串
    send_string = "C_Vis:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(spr[idx].visibility);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER]移动图层到[LAYER_MODE]
void IWall::iWall_characterSetLayer(String character, int layer_mode) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 确定新位置
    int new_idx = 0;
    switch (layer_mode) {
        // 顶层
        case 0: if (idx < spr_number - 1) new_idx = spr_number - 1; break;
        // 上一层
        case 1: if (idx < spr_number - 1) new_idx = idx + 1; break;
        // 下一层
        case 2: if (idx > 0) new_idx = idx - 1; break;
        // 底层
        case 3: if (idx > 0) new_idx = 0; break;
    }
    // 修改角色数组
    // 先删除原来的角色
    Sprite new_spr = spr[idx];
    for (int i = idx; i < spr_number; i ++) {
        spr[i] = spr[i + 1];
    }
    // 再插入到相应的位置
    for (int i = spr_number - 1 - 1; i >= new_idx; i --) {
        spr[i + 1] = spr[i];
    }
    spr[new_idx] = new_spr;
    // 拼接字符串
    send_string = "C_Idx:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(new_idx);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER]遇到边缘[EDGE_MODE]
void IWall::iWall_characterSetEdgeMode(String character, int edge_mode) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 修改角色遇到边缘的处理方式
    spr[idx].edge_mode = edge_mode;
    // 拼接字符串
    send_string = "C_EdgeMode:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(spr[idx].edge_mode);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER][FLIP]翻转
void IWall::iWall_characterFlip(String character, int flip) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 拼接字符串
    send_string = "C_Flp:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(flip);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER]遇到边缘时[FLIP_MODE]
void IWall::iWall_characterSetFlipMode(String character, int flip_mode) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return;
    // 拼接字符串
    send_string = "C_FlipMode:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(flip_mode);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 角色[CHARACTER_A]与[CHARACTER_B]是否碰撞
bool IWall::iWall_characterGetCharsCollision(String character_a, String character_b) {
    // 找到角色
    int idx_a = lookup_sprite(character_a);
    int idx_b = lookup_sprite(character_b);
    if (idx_a == -1 || idx_b == -1) return false;
    // 判断角色的长和宽与角色中心点的距离
    if (abs(spr[idx_a].center_x - spr[idx_b].center_x) < (spr[idx_a].width + spr[idx_b].width) / 2.0
        && abs(spr[idx_a].center_y - spr[idx_b].center_y) < (spr[idx_a].height + spr[idx_b].height) / 2.0) {
            return true;
        }
    return false;
}

// 获取角色[CHARACTER_A]与[CHARACTER_B]的距离
float IWall::iWall_characterGetCharsDistance(String character_a, String character_b) {
    // 找到角色
    int idx_a = lookup_sprite(character_a);
    int idx_b = lookup_sprite(character_b);
    if (idx_a == -1 || idx_b == -1) return -1;
    // 计算两个点的距离并返回
    return sqrt(pow(spr[idx_a].center_x - spr[idx_b].center_x, 2) + pow(spr[idx_a].center_y - spr[idx_b].center_y, 2));
}

// 获取角色[CHARACTER]与[EDGE]边界的距离
float IWall::iWall_characterGetCharToEdgeDistance(String character, int edge) {
    // 找到角色
    int idx = lookup_sprite(character);
    if (idx == -1) return -1;
    // 计算到边界的距离
    switch (edge) {
        // 上
        case 0: return abs(spr[idx].center_y);
        // 下
        case 1: return abs(29 - spr[idx].center_y);
        // 左
        case 2: return abs(spr[idx].center_x);
        // 右
        case 3: return abs(33 - spr[idx].center_x);
    }
}

// 设置背景为[BACKGROUND_TYPE]
void IWall::iWall_backSet(int background_type) {
    // 拼接字符串
    send_string = "B_Set:";
    send_string.concat(background_type);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 背景移动[STEP]向[MOTIONDIRECT]
void IWall::iWall_backMove(int step, int motionDirect) {
    // 拼接字符串
    send_string = "B_Mov:";
    send_string.concat(step);
    send_string.concat(",");
    send_string.concat(motionDirect);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 背景每[TIME]（毫秒）向[MOTIONDIRECT]移动一格
void IWall::iWall_backAutoMove(int time, int motionDirect) {
    // 拼接字符串
    send_string = "B_AutoMove:";
    send_string.concat(time);
    send_string.concat(",");
    send_string.concat(motionDirect);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 传感器初始化
void IWall::iWall_SensorInit(int sensor_id) {
    // 拼接字符串
    send_string = "S_Init:";
    // 传感器编号
    send_string.concat(sensor_id);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 传感器数值获取
float IWall::iWall_SensorGet(int sensor_data_id) {
    // 传感器数值编号与传感器编号映射
    // 发送相应的字符串
    switch(sensor_data_id) {
        case 0:
            Serial.write("S_Get:0\r\n");
            break;
        case 1:
        case 2:
            Serial.write("S_Get:1\r\n");
            break;
        case 3:
            Serial.write("S_Get:2\r\n");
            break;
        case 4:
            Serial.write("S_Get:3\r\n");
            break;
        case 5:
            Serial.write("S_Get:4\r\n");
            break;
        case 6:
            Serial.write("S_Get:5\r\n");
            break;
        case 7:
            Serial.write("S_Get:6\r\n");
            break;
        case 8:
        case 9:
        case 10:
            Serial.write("S_Get:7\r\n");
            break;
        case 11:
            Serial.write("S_Get:8\r\n");
            break;
        case 12:
            Serial.write("S_Get:9\r\n");
            break;
        case 13:
            Serial.write("S_Get:10\r\n");
            break;
        case 14:
            Serial.write("S_Get:11\r\n");
            break;
    }
    serial_read();
    String receive = receive_buffer;
    // 解析传感器数值
    int start = 0, end = 0;
    switch (sensor_data_id) {
        // PM2.5
        // OK:152\r\n
        case 0:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
        // 温湿度
        // OK:28,75\r\n
        case 1:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == ',') end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
        case 2:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ',') start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
        // 超声波
        // OK:84\r\n
        case 3:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
        // 人体体温
        // OK:36.8\r\n
        case 4:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
        // RFID
        // OK:20\r\n
        case 5:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            if (receive.substring(start, end + 1).equals("none")) return -999.99;
            return receive.substring(start, end + 1).toFloat();
        // 触摸按键
        // OK:7\r\n
        case 6:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            if (receive.substring(start, end + 1).equals("none")) return -999.99;
            return receive.substring(start, end + 1).toFloat();
        // 光照强度
        // OK:152\r\n
        case 7:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
        // 颜色传感器
        // OK:152,68,23\r\n
        case 8:
            for (int i = 0, j = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == ',') j ++;
                if (receive[i] == ',' && j == 1) end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
        case 9:
            for (int i = 0, j = 0; i < receive.length(); i ++) {
                if (receive[i] == ',') j ++;
                if (receive[i] == ',' && j == 1) start = i + 1;
                if (receive[i] == ',' && j == 2) end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
        case 10:
            for (int i = 0, j = 0; i < receive.length(); i ++) {
                if (receive[i] == ',') j ++;
                if (receive[i] == ',' && j == 2) start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
        // 心率
        // OK:72\r\n
        case 11:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
        // 手势
        // OK:1\r\n
        case 12:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            if (receive.substring(start, end + 1).equals("none")) return -999.99;
            return receive.substring(start, end + 1).toFloat();
        // 磁场强度
        // OK:-394\r\n
        case 13:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
        // 压力传感器
        // OK:45\r\n
        case 14:
            for (int i = 0; i < receive.length(); i ++) {
                if (receive[i] == ':') start = i + 1;
                if (receive[i] == '\r') end = i - 1;
            }
            return receive.substring(start, end + 1).toFloat();
    }
}

// 清空画布
void IWall::iWall_LEDMatrixClear() {
    Serial.write("P_Clr\r\n");
    serial_read();
}

// 红[RED]绿[GREEN]蓝[BLUE]
long IWall::iWall_RGB(int red, int green, int blue) {
    return (long(red) << 16) + (green << 8) + (blue);
}

// 画点
void IWall::iWall_LEDMatrixSetPixel(int position_x, int position_y, long color) {
    // 拼接字符串
    send_string = "P_Dot:";
    // X坐标
    send_string.concat(position_x);
    send_string.concat(",");
    // Y坐标
    send_string.concat(position_y);
    send_string.concat(",");
    // Red红色值
    send_string.concat(color >> 16);
    send_string.concat(",");
    // Green绿色值
    send_string.concat((color >> 8) & 0xff);
    send_string.concat(",");
    // Blue蓝色值
    send_string.concat((color) & 0xff);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 画直线 起 X[START_X]Y[START_Y]止 X[END_X]Y[END_Y]颜色[COLOR]
void IWall::iWall_LEDMatrixLine(int start_x, int start_y, int end_x, int end_y, long color) {
    // 拼接字符串
    send_string = "P_Lin:";
    // 起点X坐标
    send_string.concat(start_x);
    send_string.concat(",");
    // 起点Y坐标
    send_string.concat(start_y);
    send_string.concat(",");
    // 终点X坐标
    send_string.concat(end_x);
    send_string.concat(",");
    // 终点Y坐标
    send_string.concat(end_y);
    send_string.concat(",");
    // Red红色值
    send_string.concat(color >> 16);
    send_string.concat(",");
    // Green绿色值
    send_string.concat((color >> 8) & 0xff);
    send_string.concat(",");
    // Blue蓝色值
    send_string.concat((color) & 0xff);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 画矩形 左上 X[TOP_LEFT_X]Y[TOP_LEFT_Y]右下 X[BOTTOM_RIGHT_X]Y[BOTTOM_RIGHT_Y]颜色[COLOR]模式[RECT_MODE]
void IWall::iWall_LEDMatrixRect(int top_left_x, int top_left_y, int bottom_right_x, int bottom_right_y, long color, int rect_mode) {
    // 拼接字符串
    send_string = "P_Rct:";
    // 左上点X坐标
    send_string.concat(top_left_x);
    send_string.concat(",");
    // 左上点Y坐标
    send_string.concat(top_left_y);
    send_string.concat(",");
    // 右下点X坐标
    send_string.concat(bottom_right_x);
    send_string.concat(",");
    // 右下点Y坐标
    send_string.concat(bottom_right_y);
    send_string.concat(",");
    // Red红色值
    send_string.concat(color >> 16);
    send_string.concat(",");
    // Green绿色值
    send_string.concat((color >> 8) & 0xff);
    send_string.concat(",");
    // Blue蓝色值
    send_string.concat((color) & 0xff);
    send_string.concat(",");
    // 绘制模式
    send_string.concat(rect_mode);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 画面移动 方向[CANVAS_DIRECT]格数[STEP]
void IWall::iWall_LEDMatrixShift(int canvas_direct, int step) {
    // 拼接字符串
    send_string = "P_Shift:";
    // 方向
    send_string.concat(canvas_direct);
    send_string.concat(",");
    // 格数
    send_string.concat(step);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 创建文本框 X[POSITION_X]Y[POSITION_Y]字体[TEXT_FONT]宽[WIDTH]
String IWall::iWall_createTextFrame(int position_x, int position_y, int text_font, int width) {
    // 文本框名称标识符
    txt[txt_number].name = "iWall_textarea_";
    txt[txt_number].name.concat(txt_number);
    // 文本框左上角位置
    txt[txt_number].top_left_x = position_x;
    txt[txt_number].top_left_y = position_y;
    // 文本框字体
    txt[txt_number].font = text_font;
    // 文本框宽度
    txt[txt_number].width = width;
    txt_number += 1;
    txt_count += 1;
    // 拼接字符串
    send_string = "T_New:";
    send_string.concat(txt[txt_number - 1].top_left_x);
    send_string.concat(",");
    send_string.concat(txt[txt_number - 1].top_left_y);
    send_string.concat(",");
    send_string.concat(txt[txt_number - 1].font);
    send_string.concat(",");
    send_string.concat(txt[txt_number - 1].width);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
    return txt[txt_number - 1].name;
}

// 文本框[TEXTAREA]移动到 X[POSITION_X]Y[POSITION_Y]
void IWall::iWall_textSetXY(String textarea, int position_x, int position_y) {
    // 找到文本框
    int idx = lookup_textarea(textarea);
    if (idx == -1) return;
    // 更改文本框的左上角坐标
    txt[txt_number].top_left_x = position_x;
    txt[txt_number].top_left_y = position_y;
    // 拼接字符串
    send_string = "T_XY:";
    send_string.concat(idx);
    send_string.concat(",");
    send_string.concat(txt[txt_number].top_left_x);
    send_string.concat(",");
    send_string.concat(txt[txt_number].top_left_y);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 文本框[TEXTAREA]设置文字[TEXT]颜色[COLOR]
void IWall::iWall_textSetText(String textarea, String text, long color) {
    // 找到文本框
    int idx = lookup_textarea(textarea);
    if (idx == -1) return;
    // 拼接字符串
    send_string = "T_Set:";
    // 文本框标识符
    send_string.concat(idx);
    send_string.concat(",");
    // 文字内容
    send_string.concat("\"");
    send_string.concat(text);
    send_string.concat("\"");
    send_string.concat(",");
    // Red红色值
    send_string.concat(color >> 16);
    send_string.concat(",");
    // Green绿色值
    send_string.concat((color >> 8) & 0xff);
    send_string.concat(",");
    // Blue蓝色值
    send_string.concat((color) & 0xff);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 播放背景音乐[BACK_MUSIC_TYPE]
void IWall::iWall_musicBackPlay(int back_music_type) {
    // 拼接字符串
    send_string = "M_Play:";
    // 背景音乐ID
    send_string.concat(back_music_type);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}

// 背景音乐暂停
void IWall::iWall_musicBackPause() {
    Serial.write("M_Pause\r\n");
    serial_read();
}

// 背景音乐停止
void IWall::iWall_musicBackStop() {
    Serial.write("M_Stop\r\n");
    serial_read();
}

// 背景音乐继续
void IWall::iWall_musicBackResume() {
    Serial.write("M_Resume\r\n");
    serial_read();
}

// 播放声音[MUSIC_TYPE]
void IWall::iWall_musicSoundPlay(int music_type) {
    // 拼接字符串
    send_string = "M_SPlay:";
    // 音乐ID
    send_string.concat(music_type);
    send_string.concat("\r\n");
    Serial.write(send_string.c_str());
    serial_read();
}